import javax.swing.table.TableModel;
import javax.swing.event.TableModelEvent;

public class TableBubbleSortDecorator extends TableSortDecorator {
    // The lone constructor must be passed a reference to a
    // TableModel. This class decorates that model with additional
    // sorting functionality.
    public TableBubbleSortDecorator(TableModel model) {
        super(model);
        allocate();
    }

    // tableChanged is defined in TableModelListener, which
    // is implemented by TableSortDecorator.
    public void tableChanged(TableModelEvent e) {
        allocate();
    }

    // Two TableModel methods are overridden from
    // TableModelDecorator ...
    public Object getValueAt(int row, int column) {
        return getRealModel().getValueAt(indexes[row], column);
    }

    public void setValueAt(Object aValue, int row, int column) {
        getRealModel().setValueAt(aValue, indexes[row], column);
    }

    // The following methods perform the bubble sort ...

    public void sort(int column) {
        int rowCount = getRowCount();

        for (int i = 0; i < rowCount; i++) {
            for (int j = i + 1; j < rowCount; j++) {
                if (compare(indexes[i], indexes[j], column) < 0) {
                    swap(i, j);
                }
            }
        }
    }

    private void swap(int i, int j) {
        int tmp = indexes[i];
        indexes[i] = indexes[j];
        indexes[j] = tmp;
    }

    private int compare(int i, int j, int column) {
        TableModel realModel = getRealModel();
        Object io = realModel.getValueAt(i, column);
        Object jo = realModel.getValueAt(j, column);

        int c = jo.toString().compareTo(io.toString());
        return (c < 0) ? -1 : ((c > 0) ? 1 : 0);
    }

    private void allocate() {
        indexes = new int[getRowCount()];
        for (int i = 0; i < indexes.length; ++i) {
            indexes[i] = i;
        }
    }

    private int indexes[];
}
